import os
import sys
import shutil
import glob
from subprocess import run
from datetime import datetime
import platform

def get_version_input():
    """获取用户输入的版本号"""
    version = input("请输入版本号（直接回车跳过）: ").strip()
    return version if version else None

def get_version_string(version):
    """获取版本字符串"""
    if version:
        date_str = datetime.now().strftime("%Y%m%d")
        return f"_{version}_{date_str}"
    return ""

def clean_build():
    """清理构建文件夹"""
    dirs_to_clean = ['build', 'dist', 'build_specs']
    files_to_clean = ['*.spec']
    
    for dir_name in dirs_to_clean:
        if os.path.exists(dir_name):
            shutil.rmtree(dir_name)
    
    for file_pattern in files_to_clean:
        for file in glob.glob(file_pattern):
            os.remove(file)

def create_version_file(version):
    """创建版本信息文件"""
    if not version:
        return None
        
    version_parts = version.split('.')
    while len(version_parts) < 4:
        version_parts.append('0')
    
    version_tuple = tuple(map(int, version_parts))
    
    version_file = 'version.py'
    version_info = f'''
VSVersionInfo(
  ffi=FixedFileInfo(
    filevers={version_tuple},
    prodvers={version_tuple},
    mask=0x3f,
    flags=0x0,
    OS=0x40004,
    fileType=0x1,
    subtype=0x0,
    date=(0, 0)
    ),
  kids=[
    StringFileInfo(
      [
      StringTable(
        u'040904B0',
        [StringStruct(u'CompanyName', u'Snake Konginchrist'),
        StringStruct(u'FileDescription', u'图像文字识别转Word工具'),
        StringStruct(u'FileVersion', u'{version}'),
        StringStruct(u'InternalName', u'image_to_docx'),
        StringStruct(u'LegalCopyright', u'Copyright (C) 2025 Snake Konginchrist'),
        StringStruct(u'OriginalFilename', u'图像文字识别转Word工具.exe'),
        StringStruct(u'ProductName', u'图像文字识别转Word工具'),
        StringStruct(u'ProductVersion', u'{version}')])
      ]), 
    VarFileInfo([VarStruct(u'Translation', [0x0409, 1200])])
  ]
)
'''
    
    with open(version_file, 'w', encoding='utf-8') as f:
        f.write(version_info)
    
    return version_file

def build_for_platform(platform, arch, version):
    """为指定平台和架构构建可执行文件"""
    version_str = get_version_string(version)
    arch_suffix = f"_{arch}" if arch else ""
    
    # 获取当前工作目录的绝对路径
    current_dir = os.path.abspath(os.getcwd())
    
    # 创建specs目录
    specs_dir = os.path.join(current_dir, 'build_specs')
    os.makedirs(specs_dir, exist_ok=True)
    
    # 确保所有Python文件都存在并获取其绝对路径
    required_files = ['main.py', 'gui.py', 'image_processor.py']
    file_paths = {}
    for file in required_files:
        file_path = os.path.join(current_dir, file)
        if not os.path.exists(file_path):
            raise Exception(f"缺少必要的文件: {file}")
        file_paths[file] = file_path
    
    # 查找 tkdnd 库路径
    import tkinterdnd2
    tkdnd_path = os.path.dirname(tkinterdnd2.__file__)
    
    # 基本的 PyInstaller 参数
    args = [
        sys.executable,  # 使用当前Python解释器
        '-m',
        'PyInstaller',
        '--name', f'图像文字识别转Word工具_{platform}{arch_suffix}{version_str}',
        '--windowed',  # 使用GUI模式
        '--noconfirm',  # 覆盖输出目录
        '--clean',  # 清理临时文件
        '--specpath', specs_dir,  # 指定spec文件的输出目录
    ]
    
    # 添加图标（如果存在）
    icon_path = os.path.join(current_dir, 'icon.ico')
    if os.path.exists(icon_path):
        args.extend(['--icon', icon_path])
    
    # 添加 tkdnd 库
    tkdnd_lib = os.path.join(tkdnd_path, 'tkdnd')
    if os.path.exists(tkdnd_lib):
        args.extend(['--add-data', f'{tkdnd_lib}{os.pathsep}tkdnd'])
    
    # 添加所有必要的文件，使用绝对路径
    for file in required_files:
        args.extend(['--add-data', f'{file_paths[file]}{os.pathsep}.'])
    
    # 创建版本文件
    version_file = None
    if version:
        try:
            from PyInstaller.utils.win32.versioninfo import VSVersionInfo, FixedFileInfo, StringFileInfo, StringTable, StringStruct, VarFileInfo, VarStruct
            version_file = create_version_file(version)
            if version_file:
                version_file = os.path.join(current_dir, version_file)
                args.extend(['--version-file', version_file])
        except ImportError:
            print("警告: 无法导入版本信息模块，将不会包含版本信息")
    
    # 添加额外的隐藏导入
    if platform == 'windows':
        args.extend([
            '--hidden-import', 'tkinter',
            '--hidden-import', 'tkinterdnd2',
            '--hidden-import', 'tkinterdnd2.TkinterDnD',
            '--collect-all', 'tkinterdnd2',
            '--target-architecture', arch,
        ])
    elif platform == 'macos':
        args.extend([
            '--hidden-import', 'tkinter',
            '--hidden-import', 'tkinterdnd2',
            '--hidden-import', 'tkinterdnd2.TkinterDnD',
            '--hidden-import', 'PIL._tkinter_finder',
            '--collect-all', 'tkinterdnd2',
            '--target-architecture', arch,
        ])
    else:  # linux
        args.extend([
            '--hidden-import', 'tkinter',
            '--hidden-import', 'tkinterdnd2',
            '--hidden-import', 'tkinterdnd2.TkinterDnD',
            '--collect-all', 'tkinterdnd2',
            '--target-architecture', arch,
        ])
    
    # 添加主程序文件，使用绝对路径
    args.append(file_paths['main.py'])
    
    try:
        # 执行打包命令
        print(f"\n开始构建 {platform} {arch} 版本...")
        print("使用的命令:", ' '.join(args))
        
        result = run(args, capture_output=True, text=True)
        
        if result.returncode != 0:
            print("构建输出:", result.stdout)
            print("错误信息:", result.stderr)
            raise Exception("构建失败")
        
        print(f"{platform} {arch} 版本构建完成")
    finally:
        # 清理版本文件
        if version_file and os.path.exists(version_file):
            os.remove(version_file)

def main():
    try:
        # 检查是否安装了必要的包
        print("检查并安装必要的包...")
        run([sys.executable, '-m', 'pip', 'install', '--upgrade', 'pyinstaller'], check=True)
        
        # 获取版本号
        version = get_version_input()
        if version:
            print(f"使用版本号: {version}")
        else:
            print("不使用版本号")
        
        print("开始构建...")
        clean_build()
        
        # 获取当前平台信息
        current_platform = platform.system().lower()
        if current_platform == 'darwin':
            current_platform = 'macos'
        
        # 定义当前平台的架构
        if current_platform == 'windows':
            architectures = ['x86_64']  # Windows 通常只需要 x86_64
        elif current_platform == 'macos':
            architectures = ['x86_64', 'arm64']  # MacOS 支持 Intel 和 Apple Silicon
        else:  # linux
            architectures = ['x86_64']  # Linux 通常使用 x86_64
        
        # 为当前平台的每个架构构建
        for arch in architectures:
            try:
                build_for_platform(current_platform, arch, version)
            except Exception as e:
                print(f"构建 {current_platform} {arch} 版本时出错: {str(e)}")
                continue
        
        print("\n构建完成！可执行文件位于 dist 文件夹中")
        print("\n生成的文件：")
        for arch in architectures:
            print(f"- {current_platform} {arch}")
        
    except Exception as e:
        print(f"构建过程中出现错误：{str(e)}")
        sys.exit(1)

if __name__ == "__main__":
    main() 